Import Packages
library(ggplot2)
library(plotly)
library(data.table)
Import Data and look at first couple records
setwd("F:/kaggle/Mercedes-Benz")
sample_submission <- fread("data/sample_submission.csv")
train <- fread("data/train.csv")
test <- fread("data/test.csv")
train[1:2,]
# 1 - ID
# 2 - Response Varuable (Time in Seconds on Test Stand)
# 3-10 String Option Codes
# 11-385 0/1 values based on option codes
# X7 and X9 are missinf for some reason.
Calculate Mean and SD for Response Variable (Y). This is the time (sec) for a vehicle on the MB test station.
mean(train[,y])
[1] 100.6693
sd(train[,y])
[1] 12.67938
Create plots for the Response Variable. Sorted by ID.
plot_ly(y=train$y, type="scatter")
Create plots for the Response Variable. Sorted by the Response Variable.
plot_ly(y=train[order(y),]$y, type="scatter")
Create histogram for the Response Variable.
plot_ly(x=train$y, type="histogram")
Create histogram for the LOG(Response Variable).
plot_ly(x=log(train$y), type="histogram")
Frequency tables for the first 10 variables (All with String Codes)
cbind(train[,.N,by=X0],Mean_Y=round(train[,mean(y),by=X0]$V1,1))[order(-N)]
cbind(train[,.N,by=X1],Mean_Y=round(train[,mean(y),by=X1]$V1,1))[order(-N)]
cbind(train[,.N,by=X2],Mean_Y=round(train[,mean(y),by=X2]$V1,1))[order(-N)]
cbind(train[,.N,by=X3],Mean_Y=round(train[,mean(y),by=X3]$V1,1))[order(-N)]
cbind(train[,.N,by=X4],Mean_Y=round(train[,mean(y),by=X4]$V1,1))[order(-N)]
cbind(train[,.N,by=X5],Mean_Y=round(train[,mean(y),by=X5]$V1,1))[order(-N)]
cbind(train[,.N,by=X6],Mean_Y=round(train[,mean(y),by=X6]$V1,1))[order(-N)]
cbind(train[,.N,by=X8],Mean_Y=round(train[,mean(y),by=X8]$V1,1))[order(-N)]#where is 7
#where is 9
Frequency plots for the first 10 variables (All with String Codes)
# column_names_for_option_plots_string_codes <- colnames(train)[3:5] #3:12
# for(i in column_names_for_option_plots_string_codes){
# x_values <- as.data.frame(train[,.N,by=i][order(-N)])[,i]
# y_values <- as.data.frame(train[,.N,by=i][order(-N)])[,'N']
# plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar")
##Couldn't get loop plotting to work => https://github.com/ropensci/plotly/issues/273
#Plotting manually
column_names_for_option_plots_string_codes <- colnames(train)[3:10] #3:10
i<-1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)
i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)
i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)
i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)
i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)
i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)
i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)
i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)
Frequency table for the remaining variables (All with 0/1 Coding)
column_names_for_summary <- colnames(train)[11:length(colnames(train))]
Variable <- c()
N_0 <- c()
N_1 <- c()
Mean_0 <- c()
Mean_1 <- c()
for(i in column_names_for_summary){
j<-1
Variable <- c(Variable,i)
N_0 <- c(N_0,train[,.N,by=i][1]$N)
N_1 <- c(N_1,train[,.N,by=i][2]$N)
Mean_0 <- c(Mean_0,round(train[,mean(y),by=i][1]$V1,1))
Mean_1 <- c(Mean_1,round(train[,mean(y),by=i][2]$V1,1))
j <- j+1
}
# N_0[is.na(N_0)==TRUE] <- 0
# N_1[is.na(N_1)==TRUE] <- 0
# Mean_0[is.na(Mean_0)==TRUE] <- 0
# Mean_1[is.na(Mean_1)==TRUE] <- 0
summary_results <- as.data.frame(cbind(Variable,N_0=N_0,N_1,Mean_0,Mean_1), stringsAsFactors = FALSE)
summary_results$N_0 <- as.integer(summary_results$N_0)
summary_results$N_1 <- as.integer(summary_results$N_1)
summary_results$Mean_0 <- as.numeric(summary_results$Mean_0)
summary_results$Mean_1 <- as.numeric(summary_results$Mean_1)
summary_results$Delta_Mean <- summary_results$Mean_1 - summary_results$Mean_0
summary_results
After Looking at Kaggle, checked for Duplicate fileds - Added Data to Frequency table for the remaining variables (All with 0/1 Coding).
train_2 <- train[, !duplicated(t(train))] #remove duplicated fields ... from raddar@Kaggle => https://www.kaggle.com/c/mercedes-benz-greener-manufacturing/discussion/34006
duplicate_column <- c()
for(i in duplicated(t(train))){
duplicate_column <- c(duplicate_column,i)
}
duplicate_column <- duplicate_column[11:length(duplicate_column)]
summary_results$duplicate_column <- duplicate_column
summary_results_decreasing <- summary_results[order(-N_1),]
summary_results
summary_results_decreasing
List of Duplicated Columns
summary_results_decreasing[(summary_results_decreasing$duplicate_column==TRUE),]
LS0tDQp0aXRsZTogIk1lcmNlZGVzLUJlbnogRURBIE5vdGVib29rIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQphdXRob3I6IEplZmYgSGVkYmVyZw0KZGF0ZTogNS1KdW5lLTIwMTcgICAgDQotLS0NCjxicj4NCg0KIyMjIyBJbXBvcnQgUGFja2FnZXMNCmBgYHtyLHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmBgYA0KDQo8YnI+DQoNCiMjIyMgIEltcG9ydCBEYXRhIGFuZCBsb29rIGF0IGZpcnN0IGNvdXBsZSByZWNvcmRzDQpgYGB7cn0NCnNldHdkKCJGOi9rYWdnbGUvTWVyY2VkZXMtQmVueiIpDQoNCnNhbXBsZV9zdWJtaXNzaW9uIDwtIGZyZWFkKCJkYXRhL3NhbXBsZV9zdWJtaXNzaW9uLmNzdiIpDQp0cmFpbiA8LSBmcmVhZCgiZGF0YS90cmFpbi5jc3YiKQ0KdGVzdCA8LSBmcmVhZCgiZGF0YS90ZXN0LmNzdiIpDQoNCnRyYWluWzE6MixdDQoNCiMgMSAtIElEDQojIDIgLSBSZXNwb25zZSBWYXJ1YWJsZSAoVGltZSBpbiBTZWNvbmRzIG9uIFRlc3QgU3RhbmQpDQojIDMtMTAgIFN0cmluZyBPcHRpb24gQ29kZXMNCiMgMTEtMzg1IDAvMSB2YWx1ZXMgYmFzZWQgb24gb3B0aW9uIGNvZGVzDQoNCiMgWDcgYW5kIFg5IGFyZSBtaXNzaW5mIGZvciBzb21lIHJlYXNvbi4NCmBgYA0KPGJyPg0KDQojIyMjICBDYWxjdWxhdGUgTWVhbiBhbmQgU0QgZm9yIFJlc3BvbnNlIFZhcmlhYmxlIChZKS4gIFRoaXMgaXMgdGhlIHRpbWUgKHNlYykgZm9yIGEgdmVoaWNsZSBvbiB0aGUgTUIgdGVzdCBzdGF0aW9uLg0KYGBge3J9DQptZWFuKHRyYWluWyx5XSkNCnNkKHRyYWluWyx5XSkNCmBgYA0KPGJyPg0KDQojIyMjICBDcmVhdGUgcGxvdHMgZm9yIHRoZSBSZXNwb25zZSBWYXJpYWJsZS4gIFNvcnRlZCBieSBJRC4NCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQ0KcGxvdF9seSh5PXRyYWluJHksIHR5cGU9InNjYXR0ZXIiKQ0KYGBgDQo8YnI+DQoNCiMjIyMgIENyZWF0ZSBwbG90cyBmb3IgdGhlIFJlc3BvbnNlIFZhcmlhYmxlLiAgU29ydGVkIGJ5IHRoZSBSZXNwb25zZSBWYXJpYWJsZS4NCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQ0KcGxvdF9seSh5PXRyYWluW29yZGVyKHkpLF0keSwgdHlwZT0ic2NhdHRlciIpDQpgYGANCjxicj4NCg0KIyMjIyAgQ3JlYXRlIGhpc3RvZ3JhbSBmb3IgdGhlIFJlc3BvbnNlIFZhcmlhYmxlLg0KYGBge3J9DQogcGxvdF9seSh4PXRyYWluJHksIHR5cGU9Imhpc3RvZ3JhbSIpDQpgYGANCjxicj4NCg0KIyMjIyAgQ3JlYXRlIGhpc3RvZ3JhbSBmb3IgdGhlIExPRyhSZXNwb25zZSBWYXJpYWJsZSkuDQpgYGB7cn0NCiBwbG90X2x5KHg9bG9nKHRyYWluJHkpLCB0eXBlPSJoaXN0b2dyYW0iKQ0KYGBgDQo8YnI+DQoNCiMjIyMgIEZyZXF1ZW5jeSB0YWJsZXMgZm9yIHRoZSBmaXJzdCAxMCB2YXJpYWJsZXMgKEFsbCB3aXRoIFN0cmluZyBDb2RlcykNCmBgYHtyfQ0KY2JpbmQodHJhaW5bLC5OLGJ5PVgwXSxNZWFuX1k9cm91bmQodHJhaW5bLG1lYW4oeSksYnk9WDBdJFYxLDEpKVtvcmRlcigtTildDQpjYmluZCh0cmFpblssLk4sYnk9WDFdLE1lYW5fWT1yb3VuZCh0cmFpblssbWVhbih5KSxieT1YMV0kVjEsMSkpW29yZGVyKC1OKV0NCmNiaW5kKHRyYWluWywuTixieT1YMl0sTWVhbl9ZPXJvdW5kKHRyYWluWyxtZWFuKHkpLGJ5PVgyXSRWMSwxKSlbb3JkZXIoLU4pXQ0KY2JpbmQodHJhaW5bLC5OLGJ5PVgzXSxNZWFuX1k9cm91bmQodHJhaW5bLG1lYW4oeSksYnk9WDNdJFYxLDEpKVtvcmRlcigtTildDQpjYmluZCh0cmFpblssLk4sYnk9WDRdLE1lYW5fWT1yb3VuZCh0cmFpblssbWVhbih5KSxieT1YNF0kVjEsMSkpW29yZGVyKC1OKV0NCmNiaW5kKHRyYWluWywuTixieT1YNV0sTWVhbl9ZPXJvdW5kKHRyYWluWyxtZWFuKHkpLGJ5PVg1XSRWMSwxKSlbb3JkZXIoLU4pXQ0KY2JpbmQodHJhaW5bLC5OLGJ5PVg2XSxNZWFuX1k9cm91bmQodHJhaW5bLG1lYW4oeSksYnk9WDZdJFYxLDEpKVtvcmRlcigtTildDQpjYmluZCh0cmFpblssLk4sYnk9WDhdLE1lYW5fWT1yb3VuZCh0cmFpblssbWVhbih5KSxieT1YOF0kVjEsMSkpW29yZGVyKC1OKV0jd2hlcmUgaXMgNw0KI3doZXJlIGlzIDkNCg0KYGBgDQo8YnI+DQoNCiMjIyMgIEZyZXF1ZW5jeSBwbG90cyBmb3IgdGhlIGZpcnN0IDEwIHZhcmlhYmxlcyAoQWxsIHdpdGggU3RyaW5nIENvZGVzKQ0KYGBge3J9DQojIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2RlcyA8LSBjb2xuYW1lcyh0cmFpbilbMzo1XSAjMzoxMg0KIyBmb3IoaSBpbiBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXMpew0KIyAgIHhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWldW29yZGVyKC1OKV0pWyxpXQ0KIyAgIHlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWldW29yZGVyKC1OKV0pWywnTiddDQojICAgcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpDQojI0NvdWxkbid0IGdldCBsb29wIHBsb3R0aW5nIHRvIHdvcmsgPT4gaHR0cHM6Ly9naXRodWIuY29tL3JvcGVuc2NpL3Bsb3RseS9pc3N1ZXMvMjczDQoNCiNQbG90dGluZyBtYW51YWxseQ0KY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzIDwtIGNvbG5hbWVzKHRyYWluKVszOjEwXSAjMzoxMA0KaTwtMQ0KY3VycmVudF9jb2xuYW1lIDwtIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlc1tpXQ0KeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssY3VycmVudF9jb2xuYW1lXQ0KeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssJ04nXQ0KcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpICU+JSBsYXlvdXQodGl0bGU9Y3VycmVudF9jb2xuYW1lKQ0KaTwtaSsxDQpjdXJyZW50X2NvbG5hbWUgPC0gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzW2ldDQp4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWyxjdXJyZW50X2NvbG5hbWVdDQp5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWywnTiddDQpwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikgJT4lIGxheW91dCh0aXRsZT1jdXJyZW50X2NvbG5hbWUpDQppPC1pKzENCmN1cnJlbnRfY29sbmFtZSA8LSBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXNbaV0NCnhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLGN1cnJlbnRfY29sbmFtZV0NCnlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLCdOJ10NCnBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKSAlPiUgbGF5b3V0KHRpdGxlPWN1cnJlbnRfY29sbmFtZSkNCmk8LWkrMQ0KY3VycmVudF9jb2xuYW1lIDwtIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlc1tpXQ0KeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssY3VycmVudF9jb2xuYW1lXQ0KeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssJ04nXQ0KcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpICU+JSBsYXlvdXQodGl0bGU9Y3VycmVudF9jb2xuYW1lKQ0KaTwtaSsxDQpjdXJyZW50X2NvbG5hbWUgPC0gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzW2ldDQp4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWyxjdXJyZW50X2NvbG5hbWVdDQp5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWywnTiddDQpwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikgJT4lIGxheW91dCh0aXRsZT1jdXJyZW50X2NvbG5hbWUpDQppPC1pKzENCmN1cnJlbnRfY29sbmFtZSA8LSBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXNbaV0NCnhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLGN1cnJlbnRfY29sbmFtZV0NCnlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLCdOJ10NCnBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKSAlPiUgbGF5b3V0KHRpdGxlPWN1cnJlbnRfY29sbmFtZSkNCmk8LWkrMQ0KY3VycmVudF9jb2xuYW1lIDwtIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlc1tpXQ0KeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssY3VycmVudF9jb2xuYW1lXQ0KeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssJ04nXQ0KcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpICU+JSBsYXlvdXQodGl0bGU9Y3VycmVudF9jb2xuYW1lKQ0KaTwtaSsxDQpjdXJyZW50X2NvbG5hbWUgPC0gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzW2ldDQp4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWyxjdXJyZW50X2NvbG5hbWVdDQp5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWywnTiddDQpwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikgJT4lIGxheW91dCh0aXRsZT1jdXJyZW50X2NvbG5hbWUpDQoNCmBgYA0KPGJyPg0KDQojIyMjICBGcmVxdWVuY3kgdGFibGUgZm9yIHRoZSByZW1haW5pbmcgdmFyaWFibGVzIChBbGwgd2l0aCAwLzEgQ29kaW5nKQ0KYGBge3J9DQpjb2x1bW5fbmFtZXNfZm9yX3N1bW1hcnkgPC0gY29sbmFtZXModHJhaW4pWzExOmxlbmd0aChjb2xuYW1lcyh0cmFpbikpXQ0KVmFyaWFibGUgPC0gYygpDQpOXzAgPC0gYygpDQpOXzEgPC0gYygpDQpNZWFuXzAgPC0gYygpDQpNZWFuXzEgPC0gYygpDQoNCmZvcihpIGluIGNvbHVtbl9uYW1lc19mb3Jfc3VtbWFyeSl7DQogIGo8LTENCiAgVmFyaWFibGUgPC0gYyhWYXJpYWJsZSxpKQ0KICBOXzAgPC0gYyhOXzAsdHJhaW5bLC5OLGJ5PWldWzFdJE4pDQogIE5fMSA8LSBjKE5fMSx0cmFpblssLk4sYnk9aV1bMl0kTikNCiAgTWVhbl8wIDwtIGMoTWVhbl8wLHJvdW5kKHRyYWluWyxtZWFuKHkpLGJ5PWldWzFdJFYxLDEpKQ0KICBNZWFuXzEgPC0gYyhNZWFuXzEscm91bmQodHJhaW5bLG1lYW4oeSksYnk9aV1bMl0kVjEsMSkpDQogIGogPC0gaisxDQp9DQoNCiMgTl8wW2lzLm5hKE5fMCk9PVRSVUVdIDwtIDANCiMgTl8xW2lzLm5hKE5fMSk9PVRSVUVdIDwtIDANCiMgTWVhbl8wW2lzLm5hKE1lYW5fMCk9PVRSVUVdIDwtIDANCiMgTWVhbl8xW2lzLm5hKE1lYW5fMSk9PVRSVUVdIDwtIDANCg0Kc3VtbWFyeV9yZXN1bHRzIDwtIGFzLmRhdGEuZnJhbWUoY2JpbmQoVmFyaWFibGUsTl8wPU5fMCxOXzEsTWVhbl8wLE1lYW5fMSksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCnN1bW1hcnlfcmVzdWx0cyROXzAgPC0gYXMuaW50ZWdlcihzdW1tYXJ5X3Jlc3VsdHMkTl8wKQ0Kc3VtbWFyeV9yZXN1bHRzJE5fMSA8LSBhcy5pbnRlZ2VyKHN1bW1hcnlfcmVzdWx0cyROXzEpDQpzdW1tYXJ5X3Jlc3VsdHMkTWVhbl8wIDwtIGFzLm51bWVyaWMoc3VtbWFyeV9yZXN1bHRzJE1lYW5fMCkNCnN1bW1hcnlfcmVzdWx0cyRNZWFuXzEgPC0gYXMubnVtZXJpYyhzdW1tYXJ5X3Jlc3VsdHMkTWVhbl8xKQ0Kc3VtbWFyeV9yZXN1bHRzJERlbHRhX01lYW4gPC0gc3VtbWFyeV9yZXN1bHRzJE1lYW5fMSAtIHN1bW1hcnlfcmVzdWx0cyRNZWFuXzANCnN1bW1hcnlfcmVzdWx0cw0KYGBgDQo8YnI+DQoNCiMjIyMgIEFmdGVyIExvb2tpbmcgYXQgS2FnZ2xlLCBjaGVja2VkIGZvciBEdXBsaWNhdGUgZmlsZWRzIC0gQWRkZWQgRGF0YSB0byBGcmVxdWVuY3kgdGFibGUgZm9yIHRoZSByZW1haW5pbmcgdmFyaWFibGVzIChBbGwgd2l0aCAwLzEgQ29kaW5nKS4NCmBgYHtyfQ0KdHJhaW5fMiA8LSB0cmFpblssICFkdXBsaWNhdGVkKHQodHJhaW4pKV0gI3JlbW92ZSBkdXBsaWNhdGVkIGZpZWxkcyAuLi4gZnJvbSByYWRkYXJAS2FnZ2xlID0+IGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vYy9tZXJjZWRlcy1iZW56LWdyZWVuZXItbWFudWZhY3R1cmluZy9kaXNjdXNzaW9uLzM0MDA2DQpkdXBsaWNhdGVfY29sdW1uIDwtIGMoKQ0KZm9yKGkgaW4gZHVwbGljYXRlZCh0KHRyYWluKSkpew0KICBkdXBsaWNhdGVfY29sdW1uIDwtIGMoZHVwbGljYXRlX2NvbHVtbixpKQ0KfQ0KDQpkdXBsaWNhdGVfY29sdW1uIDwtIGR1cGxpY2F0ZV9jb2x1bW5bMTE6bGVuZ3RoKGR1cGxpY2F0ZV9jb2x1bW4pXQ0KDQpzdW1tYXJ5X3Jlc3VsdHMkZHVwbGljYXRlX2NvbHVtbiA8LSBkdXBsaWNhdGVfY29sdW1uDQoNCnN1bW1hcnlfcmVzdWx0c19kZWNyZWFzaW5nIDwtIHN1bW1hcnlfcmVzdWx0c1tvcmRlcigtTl8xKSxdDQoNCnN1bW1hcnlfcmVzdWx0cw0Kc3VtbWFyeV9yZXN1bHRzX2RlY3JlYXNpbmcNCmBgYA0KPGJyPg0KDQojIyMjICBMaXN0IG9mIER1cGxpY2F0ZWQgQ29sdW1ucw0KYGBge3J9DQpzdW1tYXJ5X3Jlc3VsdHNfZGVjcmVhc2luZ1soc3VtbWFyeV9yZXN1bHRzX2RlY3JlYXNpbmckZHVwbGljYXRlX2NvbHVtbj09VFJVRSksXQ0KYGBgDQo8YnI+DQoNCg0KDQo=